package com.binarycube.webserver;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;

import com.binarycube.cubecore.common.DateTime;
import com.binarycube.webserver.config.PageConfig;
import com.binarycube.webserver.config.ServerConfig;
import com.binarycube.webserver.datasource.DataManager;
import com.binarycube.webserver.session.ISessionManager;
import com.binarycube.webserver.session.Session;
import com.binarycube.webserver.wrappers.WrappedRequest;
import com.binarycube.webserver.wrappers.WrappedResponse;
import com.binarycube.webserver.wrappers.WrappedSession;

import freemarker.template.Configuration;
import freemarker.template.Template;

public class PageHandler extends AbstractHandler {

	static Logger log = Logger.getLogger(PageHandler.class.getName());
	
	ServerConfig serverConfig;
	//Freemarker config
    Configuration freemarkerConfig;
	
	public PageHandler(ServerConfig config){
		serverConfig = config;
		freemarkerConfig = new Configuration();

	    // Set Directory for templates
	    try {
			freemarkerConfig.setDirectoryForTemplateLoading(new File(config.getPageBase()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
	}
	



	
	@Override
	public void handle(String target, final Request baseRequest,HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		//Server wide response settings
	  
	     response.setCharacterEncoding("UTF-8");
	     //Wrap the request for processing
	     WrappedRequest wrappedRequest = new WrappedRequest(request);
	     WrappedResponse wrappedResponse = new WrappedResponse(response);
	     
	     ISessionManager sm = serverConfig.getSessionManager();
	     Session session = sm.getSession(wrappedRequest);
	    if (session == null) session = sm.createSession(wrappedRequest);
	     
	     sm.persistSession(wrappedResponse, session);
	     
	    try {
        		    	
	    	PageConfig pageConfig = serverConfig.getPage(target.replace("/", ""));
	    	
	    	if (pageConfig == null) {
	    		//Not found error
	    		response.sendError(HttpStatus.NOT_FOUND_404, "Page not found.");
	    		 baseRequest.setHandled(true);
	    		return;
	    	}
	    	
	    	if ((pageConfig.isPrivate()) && (!session.isAuthenicated())) {
	    		//Not authorised - redirect to login URL and set a redirect in the session to return to requested page
	    		
	    		String loginURL = serverConfig.getLoginURL();
	    		if ((loginURL == null) || (loginURL.equals(""))) {
	    			//If no login page defined, through error
    		 		response.sendError(HttpStatus.UNAUTHORIZED_401, "You are unathorized to access this page.");
    		 		baseRequest.setHandled(true);
    		 		return;
	    		} else {
	    			session.setProperty(Session.REDIRECT, baseRequest.getUri().toString());
	    			sm.updateSession(session);
	    			response.sendRedirect(loginURL);
	    			response.flushBuffer();
	                baseRequest.setHandled(true);
	    		}
	    	}
	    	
	    	//See if we are viewing the source
			if (wrappedRequest.hasParameter("viewSource")) {
				//If so, return the source code for the script and exit
				//response.setContentType("text/javascript");
				String template = FileUtils.readFileToString(new File("etc/PageView.txt"));
				String source = FileUtils.readFileToString(new File(serverConfig.getPageBase() + File.separatorChar + pageConfig.getSource()));
				response.getWriter().print(template.replace("{page}", source));
				response.setStatus(HttpServletResponse.SC_OK);
				response.flushBuffer();
				baseRequest.setHandled(true);
				return;
			}
	    	
	    	
	    	
	    	if ((pageConfig != null) && (pageConfig.getSource() != null)) {
	    		
	    		HashMap<String,Object> serverData = new HashMap<String,Object>();
	    		serverData.put("name", serverConfig.getName());
	    		serverData.put("login", serverConfig.getLoginURL());
	    		serverData.put("time", new DateTime(System.currentTimeMillis()) );
	    		
	    		//Render the page with datasources
        		Map<String, Object> data = new HashMap<String, Object>();
        		data.put("request", wrappedRequest);
        		data.put("response", wrappedResponse);
        		data.put("server", serverData);
        		data.put("session", new WrappedSession(session));
        		data.put("data", DataManager.getInstance());
        		
        		Template template = freemarkerConfig.getTemplate(pageConfig.getSource());
        		template.process(data, response.getWriter());
        		
       
        		response.setStatus(HttpServletResponse.SC_OK);
        		response.flushBuffer();
                baseRequest.setHandled(true);
	        	
	    	} else {
	    		//Not found
	       		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                baseRequest.setHandled(true);
        	}
        	
       		
        } catch (Exception e) {
        	log.error("Error handling page request: ", e);
        	response.sendError(HttpStatus.INTERNAL_SERVER_ERROR_500, "Oops, there has been a problem in the server:" + e.getLocalizedMessage());
        	 baseRequest.setHandled(true);
        } 
		
		
	}
	

	

}

